/*******************************************************************************
 * Copyright (c) 2006 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/
package com.cea.papyrus.tabbedproperties.section;

import org.eclipse.emf.common.notify.Notifier;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.views.properties.tabbed.ITabbedPropertyConstants;
import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage;
import org.eclipse.uml2.uml.Action;
import org.eclipse.uml2.uml.ActionExecutionSpecification;
import org.eclipse.uml2.uml.Behavior;
import org.eclipse.uml2.uml.BehaviorExecutionSpecification;
import org.eclipse.uml2.uml.UMLPackage;

import com.cea.papyrus.core.PapyrusPlugin;
import com.cea.papyrus.core.listener.UmlElementListener;
import com.cea.papyrus.core.tabbedproperties.PropertyViewSection;
import com.cea.papyrus.core.ui.dialogs.UmlGenericTreeSelectionDialog;
import com.cea.papyrus.core.utils.LookForElement;

/**
 * @author ymortier <yann.mortier@obeo.fr>
 */
public class ExecutionSpecificationSection extends PropertyViewSection {

    /** Buttons used in the section */
    protected Button browseButton, removeButton;

    /** The name. */
    protected CLabel descLabel;

    /** Associated label */
    protected CLabel label;

    /** The parent Composite */
    protected Composite parent;

    /** Listener for the delete button */
    protected MouseListener removeButtonListener;

    /** Listener for the browse button */
    protected MouseListener browseButtonListener;

    /** Image for the remove button */
    protected final org.eclipse.swt.graphics.Image remove_img =
            PapyrusPlugin.getImage(PapyrusPlugin.PAPYRUS_ICONS_16x16 + "Delete_16x16.gif");

    /** Image for the add button */
    protected final org.eclipse.swt.graphics.Image add_img =
            PapyrusPlugin.getImage(PapyrusPlugin.PAPYRUS_ICONS_16x16 + "Add_16x16.gif");

    @Override
    public void createControls(Composite parent, TabbedPropertySheetPage tabbedPropertySheetPage) {
        super.createControls(parent, tabbedPropertySheetPage);
        Composite composite = getWidgetFactory().createFlatFormComposite(parent);
        this.parent = parent;
        parent.setLayout(new FormLayout());
        FormData data;
        data = new FormData();

        // label creation
        descLabel = getWidgetFactory().createCLabel(composite, "Behavior:"); //$NON-NLS-1$
        if (getElement() instanceof ActionExecutionSpecification) {
            descLabel.setText("Action:");
        }

        // removeButton layout
        removeButton = getWidgetFactory().createButton(composite, "", SWT.PUSH);
        removeButton.setImage(remove_img);
        data = new FormData();
        data.right = new FormAttachment(100, -ITabbedPropertyConstants.HSPACE);
        data.top = new FormAttachment(0, ITabbedPropertyConstants.HSPACE);
        removeButton.setLayoutData(data);

        // browseButton layout
        browseButton = getWidgetFactory().createButton(composite, "", SWT.PUSH);
        browseButton.setImage(add_img);
        data = new FormData();
        data.right = new FormAttachment(removeButton, -ITabbedPropertyConstants.HSPACE);
        data.top = new FormAttachment(0, ITabbedPropertyConstants.HSPACE);
        browseButton.setLayoutData(data);

        // value label
        label = getWidgetFactory().createCLabel(composite, "", SWT.BORDER);
        data = new FormData();
        data.left = new FormAttachment(0, STANDARD_LABEL_WIDTH);
        data.right = new FormAttachment(browseButton, -ITabbedPropertyConstants.HSPACE);
        data.top = new FormAttachment(0, ITabbedPropertyConstants.HSPACE);
        label.setLayoutData(data);

        // listeners setting
        browseButtonListener = new BrowseButtonlistener();
        browseButton.addMouseListener(browseButtonListener);
        removeButtonListener = new RemoveButtonlistener();
        removeButton.addMouseListener(removeButtonListener);
    }

    /**
     * Refreshes the section.
     */
    @Override
    public void refresh() {
        if (!browseButton.isDisposed()) {
            if (getElement() instanceof ActionExecutionSpecification) {
                Action action = ((ActionExecutionSpecification) getElement()).getAction();
                if (action == null) {
                    if (!label.isDisposed())
                        label.setText("<UNDEFINED>");
                    if (!removeButton.isDisposed())
                        removeButton.setEnabled(false);
                } else {
                    if (!label.isDisposed())
                        label.setText(action.getQualifiedName());
                    if (!removeButton.isDisposed())
                        removeButton.setEnabled(true);
                }
                if (!descLabel.isDisposed()) {
                    descLabel.setText("Action:");
                }
            }
            if (getElement() instanceof BehaviorExecutionSpecification) {
                Behavior behavior = ((BehaviorExecutionSpecification) getElement()).getBehavior();
                if (behavior == null) {
                    if (!label.isDisposed())
                        label.setText("<UNDEFINED>");
                    if (!removeButton.isDisposed())
                        removeButton.setEnabled(false);
                } else {
                    if (!label.isDisposed())
                        label.setText(behavior.getQualifiedName());
                    if (!removeButton.isDisposed())
                        removeButton.setEnabled(true);
                }
                if (!descLabel.isDisposed()) {
                    descLabel.setText("Behavior:");
                }
            }
        }
    }

    /**
     * Listener for the RemoveButton. Specific behavior is implemented in
     * removeButtonPressed.
     */
    protected class RemoveButtonlistener implements MouseListener {

        /**
         * Does nothing.
         * 
         * @param e
         *            MouseEvent.
         */
        public void mouseDoubleClick(MouseEvent e) {
        }

        /**
         * Does nothing.
         * 
         * @param e
         *            MouseEvent.
         */
        public void mouseDown(MouseEvent e) {
        }

        /**
         * Calls the removeButtonPressed() which does the job then refresh().
         * 
         * @param e
         *            MouseEvent.
         */
        public void mouseUp(MouseEvent e) {
            removeButtonPressed();
            refresh();
        }
    }

    /**
     * Listener for the BrowseButton. Specific behavior is implemented in
     * browseButtonPressed.
     */
    protected class BrowseButtonlistener implements MouseListener {

        /**
         * Does nothing.
         * 
         * @param e
         *            MouseEvent.
         */
        public void mouseDoubleClick(MouseEvent e) {
        }

        /**
         * Does nothing.
         * 
         * @param e
         *            MouseEvent.
         */
        public void mouseDown(MouseEvent e) {
        }

        /**
         * Calls the browseButtonPressed() which does the job then refresh().
         * 
         * @param e
         *            MouseEvent.
         */
        public void mouseUp(MouseEvent e) {
            browseButtonPressed();
            refresh();
        }
    }

    /**
     * Behavior executed when remove button is pressed.
     */
    protected void removeButtonPressed() {
        if (getElement() instanceof ActionExecutionSpecification) {
            ActionExecutionSpecification actionExecutionSpecification =
                    (ActionExecutionSpecification) getElement();
            actionExecutionSpecification.setAction(null);
        } else if (getElement() instanceof BehaviorExecutionSpecification) {
            BehaviorExecutionSpecification behaviorExecutionSpecification =
                    (BehaviorExecutionSpecification) getElement();
            behaviorExecutionSpecification.setBehavior(null);
        }
    }

    /**
     * Behavior executed when browse button is pressed.
     */
    protected void browseButtonPressed() {
        final int[] result = {
            IDialogConstants.CANCEL_ID
        };
        final UmlGenericTreeSelectionDialog dialog =
                new UmlGenericTreeSelectionDialog(parent.getShell(), LookForElement
                        .topPackage(getElement()));
        if (getElement() instanceof ActionExecutionSpecification) {
            dialog.addFilter(dialog.createMetaClassFilter(UMLPackage.eINSTANCE.getAction()));
        } else if (getElement() instanceof BehaviorExecutionSpecification) {
            dialog.addFilter(dialog.createMetaClassFilter(UMLPackage.eINSTANCE.getBehavior()));
        }

        // open dialog window
        BusyIndicator.showWhile(Display.getCurrent(), new Runnable() {
            public void run() {
                result[0] = dialog.open();
            }
        });

        // if ok was pressed, and a type was selected, set new type
        if (IDialogConstants.OK_ID == result[0]) {
            if (getElement() instanceof ActionExecutionSpecification) {
                Action action = (Action) dialog.getSelectedValue();
                ((ActionExecutionSpecification) getElement()).setAction(action);
                // add a listener
                if (graphicalElement != null) {
                    UmlElementListener _adapter = new UmlElementListener(graphicalElement);
                    ((Notifier) action).eAdapters().add(_adapter);
                }
            } else if (getElement() instanceof BehaviorExecutionSpecification) {
                Behavior behavior = (Behavior) dialog.getSelectedValue();
                ((BehaviorExecutionSpecification) getElement()).setBehavior(behavior);
                // add a listener
                if (graphicalElement != null) {
                    UmlElementListener _adapter = new UmlElementListener(graphicalElement);
                    ((Notifier) behavior).eAdapters().add(_adapter);
                }
            }
        }
    }

    /**
     * Disposes of the buttons and listeners.
     */
    public void dispose() {
        super.dispose();
        if ((removeButton != null) && !removeButton.isDisposed())
            removeButton.removeMouseListener(removeButtonListener);
        if ((browseButton != null) && !browseButton.isDisposed())
            browseButton.removeMouseListener(browseButtonListener);
    }

}
